import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';

import 'package:flutter/services.dart';
import 'package:bugly_plugin/bugly_plugin.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
//  Future.delayed(Duration(seconds: 3), () {});
  FlutterError.onError = (FlutterErrorDetails details) {
    reportErrorAndLog(details);
  };

  ///Flutter中与一个Zone的概念，Dart中可通过Zone表示指定代码执行的环境，不同的Zone代码上下文是不同的互不影响。类似一个沙盒概念，不同沙箱的之间是隔离的，沙箱可以捕获、拦截或修改一些代码行为，我们可以再这里面捕获所有没有被处理过的异常
  runZoned(
      () {
        runApp(MyApp());
      },
      zoneSpecification: ZoneSpecification(

          ///zoneSpecification：Zone的一些配置，可以自定义一些代码行为，比如拦截日志输出行为等
//    print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
//    },
          ),
      onError: (dynamic error, StackTrace stack) {
        var details = makeDetails(error, stack);
        reportErrorAndLog(details);
      });
}

///自定义上报flutter错误
reportErrorAndLog(FlutterErrorDetails details) {
  //TODO 具体实现可以通过 MethodChannel 传递给Native
  print(
      'customerReport-error:${details.exceptionAsString()}, stack:\n${details.stack.toString()}');
  BuglyPlugin.postDartError(
      details.exceptionAsString(), details.stack.toString());
}

makeDetails(dynamic error, StackTrace stack) {
  return FlutterErrorDetails(
    exception: error,
    stack: stack,
  );
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _platformVersion = 'Unknown';

  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    try {
      platformVersion = await BuglyPlugin.platformVersion;
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _platformVersion = platformVersion;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
            child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text('Running on: $_platformVersion\n'),
            RaisedButton(
              child: Text('原生异常测试'),
              onPressed: () {
                BuglyPlugin.postTestError();
              },
            ),
            Offstage(
              offstage: !Platform.isAndroid,
              child: RaisedButton(
                child: Text('ANR异常测试'),
                onPressed: () {
                  BuglyPlugin.postANRError();
                },
              ),
            ),
            Offstage(
              offstage: !Platform.isAndroid,
              child: RaisedButton(
                child: Text('Native异常测试'),
                onPressed: () {
                  BuglyPlugin.postNativeError();
                },
              ),
            ),
            RaisedButton(
              child: Text('dart异常测试'),
              onPressed: () {
                dynamic d = 1;
                print('d.length: ${d.size()}');
              },
            ),
          ],
        )),
      ),
    );
  }
}
